/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tonyodev.fetchapp.ability;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.AbsButton;
import ohos.agp.components.Component;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Switch;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.ToastDialog;
import ohos.bundle.IBundleManager;

import com.tonyodev.fetch2.AbstractFetchListener;
import com.tonyodev.fetch2.Download;
import com.tonyodev.fetch2.Error;
import com.tonyodev.fetch2.Fetch;
import com.tonyodev.fetch2.FetchConfiguration;
import com.tonyodev.fetch2.FetchListener;
import com.tonyodev.fetch2.NetworkType;
import com.tonyodev.fetch2.Request;
import com.tonyodev.fetch2core.Downloader;
import com.tonyodev.fetch2okhttp.OkHttpDownloader;
import com.tonyodev.fetchapp.ActionListener;
import com.tonyodev.fetchapp.Data;
import com.tonyodev.fetchapp.FileProvider;
import com.tonyodev.fetchapp.ResourceTable;
import com.tonyodev.fetchapp.snackbar.SnackBar;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import timber.log.Timber;

import static ohos.security.SystemPermission.WRITE_USER_STORAGE;

/**
 * xinglu
 *
 * @since 2021-05-20
 */
public class DownloadListAbility extends Ability implements ActionListener {

    private static final int STORAGE_PERMISSION_CODE = 200;
    private static final long UNKNOWN_REMAINING_TIME = -1;
    private static final long UNKNOWN_DOWNLOADED_BYTES_PER_SECOND = 0;
    private static final int GROUP_ID = "listGroup".hashCode();
    static final String FETCH_NAMESPACE = "DownloadListActivity";
    private Component mainView;
    private Fetch fetch;
    private FileProvider fileAdapter;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        getWindow().setStatusBarColor(Color.getIntColor("#303f9f"));
        super.setUIContent(ResourceTable.Layout_ability_download_list);

        setUpViews();
        final FetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this)
            .setDownloadConcurrentLimit(4)
            .setHttpDownloader(new OkHttpDownloader(Downloader.FileDownloaderType.PARALLEL))
            .setNamespace(FETCH_NAMESPACE)
            .build();

        fetch = Fetch.Impl.getInstance(fetchConfiguration);
        checkStoragePermissions();
    }


    private void setUpViews() {
        Switch mNetworkSwitch = (Switch) findComponentById(ResourceTable.Id_networkSwitch);
        ListContainer mRecyclerView = (ListContainer) findComponentById(ResourceTable.Id_recyclerView);
        mainView = findComponentById(ResourceTable.Id_activity_main);

        mNetworkSwitch.setCheckedStateChangedListener(new AbsButton.CheckedStateChangedListener() {
            @Override
            public void onCheckedChanged(AbsButton absButton, boolean isChecked) {
                if (isChecked) {
                    fetch.setGlobalNetworkType(NetworkType.WIFI_ONLY);
                } else {
                    fetch.setGlobalNetworkType(NetworkType.ALL);
                }
            }
        });

        fileAdapter = new FileProvider(this,this);
        mRecyclerView.setItemProvider(fileAdapter);
        mRecyclerView.setLongClickable(false);
    }

    private void checkStoragePermissions() {
        // 权限申请
        List<String> permissionsToRequest = new ArrayList<>();
        String[] permissions = new String[]{WRITE_USER_STORAGE};
        for (String permission : permissions) {
            if (verifyCallingPermission(permission) != IBundleManager.PERMISSION_GRANTED) {
                // 应用未被授予权限
                if (canRequestPermission(permission)) { // 是否可以申请弹框授权 如果可以就把权限添加到列表中
                    permissionsToRequest.add(permission);
                }
            }
        }

        if (!permissionsToRequest.isEmpty()) { //
            requestPermissionsFromUser(permissions, STORAGE_PERMISSION_CODE); // 说明有权限没有申请
        } else {
            enqueueDownloads();
        }
    }

    @Override
    public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsFromUserResult(requestCode, permissions, grantResults);
        if (requestCode == STORAGE_PERMISSION_CODE) {
            enqueueDownloads();
        } else {
            new SnackBar.Builder(DownloadListAbility.this, mainView)
                .withMessage(getString(ResourceTable.String_permission_not_enabled))
                .show();
        }
    }

    private void enqueueDownloads() {

        final List<Request> requests = Data.getFetchRequestWithGroupId(GROUP_ID, this);
        fetch.enqueue(requests, updatedRequests -> {

        });
        Timber.d("enqueueDownloads:" + requests.size());
    }

    @Override
    public void onPauseDownload(int id) {
        fetch.pause(id);
    }

    @Override
    public void onResumeDownload(int id) {
        fetch.resume(id);
    }

    @Override
    public void onRemoveDownload(int id) {
        fetch.remove(id);
    }

    @Override
    public void onRetryDownload(int id) {
        fetch.retry(id);
    }

    @Override
    protected void onActive() {
        super.onActive();
        fetch.getDownloadsInGroup(GROUP_ID, downloads -> {
            final ArrayList<Download> list = new ArrayList<>(downloads);
            Collections.sort(list, (first, second) -> Long.compare(first.getCreated(), second.getCreated()));
            for (Download download : list) {
                fileAdapter.addDownload(download);
            }
            Timber.d("fileAdapter.getCount:"+fileAdapter.getCount() + ", list.size:"+list.size());
        }).addListener(fetchListener);
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        fetch.removeListener(fetchListener);
    }

    @Override
    protected void onStop() {
        super.onStop();
        fetch.close();
    }

    private final FetchListener fetchListener = new AbstractFetchListener() {
        @Override
        public void onAdded(@NotNull Download download) {
            fileAdapter.addDownload(download);
        }

        @Override
        public void onQueued(Download download, boolean waitingOnNetwork) {
            fileAdapter.update(download, UNKNOWN_REMAINING_TIME, UNKNOWN_DOWNLOADED_BYTES_PER_SECOND);
        }

        @Override
        public void onCompleted(@NotNull Download download) {
            fileAdapter.update(download, UNKNOWN_REMAINING_TIME, UNKNOWN_DOWNLOADED_BYTES_PER_SECOND);
        }

        @Override
        public void onError(@NotNull Download download, @NotNull Error error, @Nullable Throwable throwable) {
            super.onError(download, error, throwable);
            fileAdapter.update(download, UNKNOWN_REMAINING_TIME, UNKNOWN_DOWNLOADED_BYTES_PER_SECOND);
        }

        @Override
        public void onProgress(Download download, long etaInMilliseconds, long downloadedBytesPerSecond) {
            fileAdapter.update(download, etaInMilliseconds, downloadedBytesPerSecond);
        }

        @Override
        public void onPaused(@NotNull Download download) {
            fileAdapter.update(download, UNKNOWN_REMAINING_TIME, UNKNOWN_DOWNLOADED_BYTES_PER_SECOND);
        }

        @Override
        public void onResumed(@NotNull Download download) {
            fileAdapter.update(download, UNKNOWN_REMAINING_TIME, UNKNOWN_DOWNLOADED_BYTES_PER_SECOND);
        }

        @Override
        public void onCancelled(@NotNull Download download) {
            fileAdapter.update(download, UNKNOWN_REMAINING_TIME, UNKNOWN_DOWNLOADED_BYTES_PER_SECOND);
        }

        @Override
        public void onRemoved(@NotNull Download download) {
            fileAdapter.update(download, UNKNOWN_REMAINING_TIME, UNKNOWN_DOWNLOADED_BYTES_PER_SECOND);
        }

        @Override
        public void onDeleted(@NotNull Download download) {
            fileAdapter.update(download, UNKNOWN_REMAINING_TIME, UNKNOWN_DOWNLOADED_BYTES_PER_SECOND);
        }
    };
}
